﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using System.Threading;

namespace SharpSoft.WPF.Controls

{
    /// <summary>
    /// 帧动画控件 （已废弃，当前帧动画控件存在诸多BUG，请使用新的帧动画播放器<see cref="FrameImagesPlayer"/>。）
    /// </summary>
    [Obsolete("已废弃，当前帧动画控件存在诸多BUG，请使用新的帧动画播放器[FrameImagesPlayer]。")]
    public class FramesImage : Control
    {
        static FramesImage()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(FramesImage), new FrameworkPropertyMetadata(typeof(FramesImage)));

        }
        public FramesImage()
        {
            waithandle = new AutoResetEvent(true);
            this.Loaded += FramesImage_Loaded;
            this.Unloaded += FramesImage_Unloaded;
        }

        private void FramesImage_Loaded(object sender, RoutedEventArgs e)
        {
            this.Dispatcher.ShutdownStarted += Dispatcher_ShutdownStarted;
        }

        private void Dispatcher_ShutdownStarted(object sender, EventArgs e)
        {
            this.Stop();
        }

        private void FramesImage_Unloaded(object sender, RoutedEventArgs e)
        {
            this.Stop();
        }
        ~FramesImage()
        {
            this.Stop();
        }

        private Thread backthread;
        private AutoResetEvent waithandle;
        private object asyncobj = new object();

        private string[] source = null;

        private string _SourceDirectory;
        /// <summary>
        /// 获取或设置帧动画图像所在的文件夹
        /// </summary>
        public string SourceDirectory
        {
            get { return _SourceDirectory; }
            set
            {
                if (_SourceDirectory != value)
                {
                    _SourceDirectory = value;
                    this.ResetSource();
                }
            }
        }
        /// <summary>
        /// 总帧数
        /// </summary>
        public int FramesCount
        {
            get
            {
                if (source == null)
                {
                    return 0;
                }
                return source.Length;
            }
        }

        private int curindex = 0;
        public int CurrentFrameIndex { get { return curindex; } }

        private int waittime = 1000 / 24;


        private int _Framerate = 35;
        /// <summary>
        /// 帧率1-60
        /// </summary>
        public int Framerate
        {
            get { return _Framerate; }
            set
            {
                _Framerate = value;
                waittime = 1000 / value;
            }
        }
        /// <summary>
        /// 是否逆向播放
        /// </summary>
        public bool Reverse { get; set; } = false;

        private PlayMode _PlayMode = PlayMode.Loop;
        /// <summary>
        /// 播放模式，循环或单次播放
        /// </summary>
        public PlayMode PlayMode
        {
            get { return _PlayMode; }
            set { _PlayMode = value; }
        }


        private PlayState _Status = PlayState.Stop;
        /// <summary>
        /// 获取当前状态，播放中，已停止，已暂停
        /// </summary>
        public PlayState Status
        {
            get { return _Status; }
        }

        /// <summary>
        /// 重置当前播放源
        /// </summary>
        protected virtual void ResetSource()
        {
            if (string.IsNullOrWhiteSpace(this.SourceDirectory) || !Directory.Exists(this.SourceDirectory))
            {//文件夹不存在
                source = null;
            }
            else
            {
                var files = Directory.GetFiles(this.SourceDirectory);
                List<string> fs = new List<string>();
                foreach (var item in files)
                {
                    var ext = System.IO.Path.GetExtension(item);
                    if (ext != null)
                    {
                        ext = ext.ToLower();
                        if (ext == ".jpg" || ext == ".png")
                        {
                            fs.Add(item);
                        }
                    }
                }
                source = fs.ToArray();
            }
            loadcurimage();
            repaint();
        }
        /// <summary>
        /// 开始播放动画
        /// </summary>
        public void Play()
        {
            if (backthread == null || backthread.ThreadState == ThreadState.Stopped)
            {
                backthread = new Thread(new ThreadStart(threadWhile));
                backthread.Start();
            }
            lock (asyncobj)
            {
                _Status = PlayState.Play;
                waithandle.Set();
            }
        }
        /// <summary>
        /// 暂停播放动画
        /// </summary>
        public void Pause()
        {
            lock (asyncobj)
            {
                _Status = PlayState.Pause;
            }
        }
        /// <summary>
        /// 停止播放动画
        /// </summary>
        public void Stop()
        {
            lock (asyncobj)
            {
                _Status = PlayState.Stop;
            }
            //if (backthread != null)
            //{
            //    backthread.Abort();
            //}
            //backthread = null;
            curindex = 0;
            //loadcurimage();
            //repaint();
        }
        /// <summary>
        /// 强制设置当前帧
        /// </summary>
        /// <param name="index"></param>
        public void SetFrame(int index)
        {
            curindex = index;
            loadcurimage();
            this.repaint();
        }
        private void loadcurimage()
        {
            if (!Dispatcher.CheckAccess())
            {
                if (Dispatcher.HasShutdownStarted || Dispatcher.HasShutdownFinished)
                {
                    return;
                }
                Dispatcher.Invoke(new Action(loadcurimage));
                return;
            }
            if (source != null && curindex >= 0 && curindex < source.Length)
            {
                curimg = new BitmapImage(new Uri(source[curindex], UriKind.Absolute));
            }
            else
            {
                curimg = null;
            }
        }
        private void OnCurrentFrameChanged()
        {
            if (!this.Dispatcher.CheckAccess())
            {
                this.Dispatcher.Invoke(new Action(OnCurrentFrameChanged));
                return;
            }
            this.CurrentFrameChanged?.Invoke(this, EventArgs.Empty);
        }
        /// <summary>
        /// 当前帧改变后触发
        /// </summary>
        public event EventHandler CurrentFrameChanged;

        void threadWhile()
        {
            while (true)
            {
                if (source == null || source.Length == 0)
                {
                    return;
                }
                PlayState state;
                lock (asyncobj)
                {
                    state = Status;
                }
                loadcurimage();
                this.repaint();
                try
                {
                    this.OnCurrentFrameChanged();
                }
                catch (Exception ex)
                {

                }
                if (this.Reverse)
                {
                    curindex--;
                    if (curindex < 0)
                    {
                        curindex = source.Length - 1;
                        if (PlayMode == PlayMode.Once)
                        {
                            Stop();
                        }
                    }
                }
                else
                {
                    curindex++;
                    if (curindex >= source.Length)
                    {
                        curindex = 0;
                        if (PlayMode == PlayMode.Once)
                        {
                            Stop();
                        }
                    }
                }

                switch (Status)
                {
                    case PlayState.Play:
                        Thread.Sleep(waittime);
                        break;
                    case PlayState.Pause:
                        waithandle.WaitOne();
                        break;
                    case PlayState.Stop:
                        return;
                    default:
                        throw new Exception("意外的状态。");
                }

            }
        }

        private void repaint()
        {
            if (!this.Dispatcher.CheckAccess())
            {
                if (Dispatcher.HasShutdownStarted || Dispatcher.HasShutdownFinished)
                {
                    return;
                }
                this.Dispatcher.Invoke(new Action(this.InvalidateVisual));
            }
            else
            {
                this.InvalidateVisual();
            }
        }

        private Stretch _Stretch = Stretch.Fill;

        public Stretch Stretch
        {
            get { return _Stretch; }
            set { _Stretch = value; }
        }

        private StretchDirection _StretchDirection = StretchDirection.Both;
        /// <summary>
        /// 缩放方向
        /// </summary>
        public StretchDirection StretchDirection
        {
            get { return _StretchDirection; }
            set { _StretchDirection = value; }
        }
        private static bool IsZero(double value)
        {
            return Math.Abs(value) < 2.2204460492503131E-15;
        }
        BitmapImage curimg;
        protected override Size MeasureOverride(Size inputSize)
        {
            return MeasureArrangeHelper(inputSize);
        }

        protected override Size ArrangeOverride(Size inputSize)
        {
            return MeasureArrangeHelper(inputSize);
        }
        private Size MeasureArrangeHelper(Size inputSize)
        {
            if (curimg == null)
            {
                return default(Size);
            }
            var availableSize = inputSize;
            var contentSize = new Size(curimg.Width, curimg.Height);
            var stretch = this.Stretch;
            double scw = 1.0;
            double sch = 1.0;
            bool flag = !double.IsPositiveInfinity(availableSize.Width);
            bool flag2 = !double.IsPositiveInfinity(availableSize.Height);
            if ((stretch == Stretch.Uniform || stretch == Stretch.UniformToFill || stretch == Stretch.Fill) && (flag | flag2))
            {
                scw = (IsZero(contentSize.Width) ? 0.0 : (availableSize.Width / contentSize.Width));
                sch = (IsZero(contentSize.Height) ? 0.0 : (availableSize.Height / contentSize.Height));
                if (!flag)
                {
                    scw = sch;
                }
                else
                {
                    if (!flag2)
                    {
                        sch = scw;
                    }
                    else
                    {
                        switch (stretch)
                        {
                            case Stretch.Uniform:
                                {
                                    double num3 = (scw < sch) ? scw : sch;
                                    sch = (scw = num3);
                                    break;
                                }
                            case Stretch.UniformToFill:
                                {
                                    double num4 = (scw > sch) ? scw : sch;
                                    sch = (scw = num4);
                                    break;
                                }
                        }
                    }
                }
                switch (_StretchDirection)
                {
                    case StretchDirection.UpOnly:
                        if (scw < 1.0)
                        {
                            scw = 1.0;
                        }
                        if (sch < 1.0)
                        {
                            sch = 1.0;
                        }
                        break;
                    case StretchDirection.DownOnly:
                        if (scw > 1.0)
                        {
                            scw = 1.0;
                        }
                        if (sch > 1.0)
                        {
                            sch = 1.0;
                        }
                        break;
                }
            }
            return new Size(scw * contentSize.Width, sch * contentSize.Height);
        }


        protected override void OnRender(DrawingContext dc)
        {
            //base.OnRender(drawingContext); 
            if (source != null && curindex < source.Length)
            {
                dc.DrawImage(curimg, new Rect(default(Point), this.RenderSize));
            }
        }
    }
    public enum PlayMode : byte
    {
        /// <summary>
        /// 只播放一次
        /// </summary>
        Once,
        /// <summary>
        /// 循环播放
        /// </summary>
        Loop

    }
    public enum PlayState : byte
    {
        /// <summary>
        /// 已停止
        /// </summary> 
        Stop = 0,
        /// <summary>
        /// 正在播放
        /// </summary>
        Play,
        /// <summary>
        /// 已暂停
        /// </summary>
        Pause,
    }
}
